package top.lshaci.learning.alicloud.oss.config;

import com.alibaba.alicloud.context.AliCloudProperties;
import com.alibaba.alicloud.context.oss.OssProperties;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSEncryptionClientBuilder;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.lshaci.learning.alicloud.oss.properties.OssEncryptionProperties;

import java.security.KeyPair;

/**
 * OssEncryptionConfig
 *
 * @author lshaci
 * @since 1.0.0
 */
@Slf4j
@Configuration
@AllArgsConstructor
@EnableConfigurationProperties(OssEncryptionProperties.class)
@ConditionalOnProperty(value = "oss.encryption.enabled", matchIfMissing = true)
public class OssEncryptionAutoConfiguration {

    private final OssProperties ossProperties;

    private final AliCloudProperties aliCloudProperties;

    private final OssEncryptionProperties ossEncryptionProperties;

    /**
     * 创建oss加密客户端
     *
     * @return oss加密客户端
     */
    @Bean
    public OSS ossEncryptionClient() {
        log.debug("Config oss encryption client...");

        String endpoint = ossProperties.getEndpoint();
        String accessKeyId = aliCloudProperties.getAccessKey();
        String accessKeySecret = aliCloudProperties.getSecretKey();
        KeyPair keyPair = ossEncryptionProperties.keyPair();

        // 创建主密钥RSA的描述信息，创建后不允许修改。主密钥描述信息和主密钥一一对应。
        // 如果所有的Object都使用相同的主密钥，主密钥描述信息可以为空，但后续不支持更换主密钥。
        // 如果主密钥描述信息为空，解密时无法判断文件使用的是哪个主密钥进行加密。
        // 强烈建议为每个主密钥都配置描述信息，由客户端保存主密钥和描述信息之间的对应关系（服务端不保存两者之间的对应关系）。
        // Map<String, String> matDesc = new HashMap<String, String>();
        // matDesc.put("<yourDescriptionKey>", "<yourDescriptionValue>");

        // 创建RSA加密材料。
        SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair);
        // 如果要下载并解密其他RSA密钥加密的文件，请将其他主密钥及其描述信息添加到加密材料中。
        // encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);

        // 创建RSA加密客户端。
        return new OSSEncryptionClientBuilder().build(endpoint, accessKeyId, accessKeySecret, encryptionMaterials);
    }
}
